package net.Group.AccessService;

import java.io.FileInputStream;
import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Enumeration;

import javax.swing.JTextArea;

import net.Group.MembershipService.SecureCredential;
import net.jxta.discovery.DiscoveryService;
import net.jxta.document.AdvertisementFactory;
import net.jxta.document.MimeMediaType;
import net.jxta.document.TextElement;
import net.jxta.endpoint.Message;
import net.jxta.endpoint.StringMessageElement;
import net.jxta.exception.PeerGroupException;
import net.jxta.peergroup.PeerGroup;
import net.jxta.pipe.OutputPipe;
import net.jxta.pipe.OutputPipeEvent;
import net.jxta.pipe.OutputPipeListener;
import net.jxta.pipe.PipeService;
import net.jxta.protocol.PipeAdvertisement;
import net.jxta.rendezvous.RendezVousService;
import net.jxta.rendezvous.RendezvousEvent;
import net.jxta.rendezvous.RendezvousListener;
import net.jxta.protocol.PeerGroupAdvertisement;


public class QueryOut extends Thread implements Runnable,OutputPipeListener,
RendezvousListener{

    private String myPeerID = null, myPeerName= null;
    private PeerGroup rootGroup =null;
    private PipeService myPipeService = null;
    private String groupCreatorID = null;

    private OutputPipe pipeOut =null;
    private PipeAdvertisement pipeAdv=null;
    private DiscoveryService myDiscoveryService=null;

    private RendezVousService myRendezVousService=null;
    private String msg = null;
    private String queryOperation = null;
    private SecureCredential sCred = null;
    private boolean Locationflag = false;
    private boolean Roleflag = false;
    private Message authResult = null;
    private String loc = null;
	public boolean b_authResult = false;

    public QueryOut(PeerGroup group,String op, SecureCredential secureCred) 
    {
        this.rootGroup=group; 
        this.queryOperation = op;
        this.sCred = secureCred;
        getServices();        
    }
    
    private void getServices() //This method will obtain Peer Group Services
    {
        System.out.println("[+]Obtaining Services for chat...\n");
        try{
            myRendezVousService = rootGroup.getRendezVousService();
            myRendezVousService.addListener(this);
            
        }catch(Exception e){
            System.out.println("[-]Cannot obtain RendezVous Services.");
            System.out.println("[-]Fatal Error: " + e.getMessage());
            e.printStackTrace();
            System.exit(-1);
        }
        myDiscoveryService = rootGroup.getDiscoveryService();
        myPipeService = rootGroup.getPipeService();
        myPeerID = rootGroup.getPeerID().toString();
        myPeerName = rootGroup.getPeerName();
        
        //start up the authorization pipe
        try{//Creating Pipe Advertisements from file
            FileInputStream in = new FileInputStream("authPipe.adv");
            pipeAdv = (PipeAdvertisement) AdvertisementFactory.newAdvertisement(MimeMediaType.XMLUTF8,in);
            in.close();
        }catch(IOException e){
            System.out.println("[-]Exception: " + e.getMessage());
            e.printStackTrace();
            System.exit(-1);
        }
        //log.append("[+]Chat Services sucessfully obtained.\n");
        System.out.println("[+]Authorization Query Services sucessfully obtained.\n");
    }
    
    private String getCreatorID() throws PeerGroupException{
    	PeerGroupAdvertisement pga = rootGroup.getPeerGroupAdvertisement();
    	TextElement myParam = (TextElement) pga.getServiceParam(rootGroup.membershipClassID);
    	String creator = null;
    	if (null == myParam) {
            throw new PeerGroupException("parameters for group service are missing.");
        }
		
		Enumeration enu = myParam.getChildren();
		while (enu.hasMoreElements()) {
            TextElement en = (TextElement) enu.nextElement();
            
            if (!en.getName().equals("CreatorID")) {
                continue;
            }
            
            creator = en.getTextValue();
            
		}
            
      return creator;      
    }
    
    public void createAuthorizationResultMsg(String peerid, String operation, String result){
    	
        DateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");
        Date date = new Date();
        String myTime = dateFormat.format(date).toString();
        
        authResult = new Message();
        
        StringMessageElement sme = new StringMessageElement("Type","AuthResult",null);
        StringMessageElement sme1 = new StringMessageElement("PeerID",peerid,null);
        StringMessageElement sme2 = new StringMessageElement("Operation",operation,null);
        StringMessageElement sme3 = new StringMessageElement("Result",result,null);
        StringMessageElement sme4 = new StringMessageElement("Time",myTime,null);
        
        
        authResult.addMessageElement(null,sme);
        authResult.addMessageElement(null,sme1);
        authResult.addMessageElement(null,sme2);
        authResult.addMessageElement(null,sme3);
        authResult.addMessageElement(null,sme4);
        
        this.b_authResult = true;
    	
    }
    
    public void startingPipe()
    {
    	System.out.println("[+]Creating Output Pipe.\n");
        try{
            //starting remoted advertisement to search for pipe
            myDiscoveryService.getRemoteAdvertisements(null,DiscoveryService.ADV,null,null,1);
            myPipeService.createOutputPipe(pipeAdv,this);
        }catch(Exception e){
        	System.out.println("[+]Exception: " + e.getMessage()+"\n");
            e.printStackTrace();
            System.exit(-1);
        }
        System.out.println("[+]Output Pipe Successfully Created.\n");
    }
    
    public void setMessage(String message){//This accessor will set messages that need to be sent
        this.msg = message;
    } 
    
    
    public void stopSending() //This method will stop input pipe
    {
    	pipeOut.close();
        System.out.println("[-]Input Pipe Closed for Incomming Message.\n");
    }
    
    public void outputPipeEvent(OutputPipeEvent ev)
    {
        System.out.println("[+]Sending Message.\n");
        pipeOut = ev.getOutputPipe();
        Message myMessage = null;
        
        DateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");
        Date date = new Date();
        String myTime = dateFormat.format(date).toString();
        
        if(!b_authResult)
        try{
            
            myMessage = new Message();
            //adding timestap and peers details also messages to XML tag and send them 
            StringMessageElement sme = new StringMessageElement("Type","Authorization",null);
            StringMessageElement sme5 = new StringMessageElement("ReceiverID",this.getCreatorID(),null);
            StringMessageElement sme1 = new StringMessageElement("peerName",myPeerName,null);
            StringMessageElement sme2 = new StringMessageElement("peerID",myPeerID,null);
            StringMessageElement sme3 = new StringMessageElement("Operation",queryOperation,null);
            StringMessageElement sme4 = new StringMessageElement("Time",myTime,null);
            
            myMessage.addMessageElement(null,sme);
            myMessage.addMessageElement(null,sme1);
            myMessage.addMessageElement(null,sme2);
            myMessage.addMessageElement(null,sme3);
            myMessage.addMessageElement(null,sme4);
            myMessage.addMessageElement(null,sme5);
            //Trigger the Sending            
            pipeOut.send(myMessage);
            
        }catch(Exception e)
        {
            System.out.println("[-]Exception: " + e.getMessage()+"\n");
            e.printStackTrace();
            System.exit(-1);            
        }
        else
        {
        	try {
				pipeOut.send(authResult);
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
        }
    }
    
    
    public synchronized void rendezvousEvent(RendezvousEvent event) 
    {
        if(event.getType() == event.RDVCONNECT || event.getType() == event.RDVRECONNECT){
            notify();
        }
    }
}
